<!doctype html>
<!--
@license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>

  <meta charset="utf-8">

  <script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
  <script src="../../../web-component-tester/browser.js"></script>

  <link rel="import" href="../../src/polymer-lib.html">
  <link rel="import" href="../../src/lib/lang.html">
  <link rel="import" href="../../src/lib/base.html">

</head>
<body>
<script>
suite('Polymer.Base', function() {

var Child;
var instance;

setup(function() {
  // Ensure a clean environment for each test.
  Child = Object.create(Polymer.Base);
  Child.is = 'x-child';
  Child._registerFeatures = function() {};
  Child._initFeatures = function() {};
  Child._setAttributeToProperty = function() {};
  Child.behaviors = [];
  Child._desugarBehaviors = function() {};
  instance = Object.create(Child);
  // make __proto__ work on IE10.
  if (!Object.__proto__) {
    instance.__proto__ = Child;
  }
});

suite('addFeature', function() {

  test('mixes the feature into Base', function() {
    assert.notOk(Polymer.Base.someProperty);
    Polymer.Base._addFeature({someProperty: 123});
    assert.equal(Polymer.Base.someProperty, 123);
  });

});

suite('registerCallback', function() {

  test('calls registered() after registerFeatures()', function() {
    var called = [];
    Child._registerFeatures = function() {
      called.push('1');
    };
    Child.registered = function() {
      called.push('2');
    };
    assert.deepEqual(called, []);
    Child.registerCallback();
    assert.includeMembers(called, ['1', '2']);
  });

});

suite('createdCallback', function() {

  // TODO(nevir): sinonify.
  test('calls lifecycle events in the proper order', function() {
    var called = [];
    Child.created = function() {
      called.push('created');
    };
    assert.deepEqual(called, []);
    instance.createdCallback();
    assert.deepEqual(called, ['created']);
  });

  test('calls initFeatures()', function() {
    var called = false;
    Child._initFeatures = function() {
      called = true;
    };
    instance.createdCallback();
    assert.isTrue(called);
  });

  test('calls initFeatures() with the correct `this`', function() {
    Child._initFeatures = function() {
      assert.equal(this, instance);
    };
    instance.createdCallback();
  });

});

suite('attachedCallback', function() {

  test('calls attached()', function() {
    var called = false;
    Child.attached = function() {called = true};
    instance.attachedCallback();
    assert.isTrue(called);
  });

});

suite('detachedCallback', function() {

  test('calls detached()', function() {
    var called = false;
    Child.detached = function() {called = true};
    instance.detachedCallback();
    assert.isTrue(called);
  });

});

suite('attributeChangedCallback', function() {

  test('calls attributeChanged()', function() {
    var args = null;
    Child.attributeChanged = function() {args = arguments};
    instance.attributeChangedCallback('attr', null, 1);

    assert.equal(args.length, 3);
    assert.equal(args[0], 'attr');
    assert.equal(args[1], null);
    assert.equal(args[2], 1);
  });

});

suite('Logging', function() {
  var logStub;
  setup(function() {
    logStub = sinon.stub(console, 'log');
  });
  teardown(function() {
    logStub.restore();
  });

  test('logger is an entry point for console', function() {
    Polymer.Base._logger('log', ['hi']);
    assert.equal(logStub.callCount, 1);
  });

  test('only allow logging methods', function() {
    var warnStub = sinon.stub(console, 'warn');
    var errorStub = sinon.stub(console, 'error');
    var dirStub = sinon.stub(console, 'dir');
    var args = ['hi'];
    Polymer.Base._logger('warn', args);
    Polymer.Base._logger('error', args);
    Polymer.Base._logger('dir', args);
    warnStub.restore();
    errorStub.restore();
    dirStub.restore();
    assert.equal(warnStub.callCount, 1);
    assert.equal(errorStub.callCount, 1);
    assert.equal(dirStub.callCount, 0);
  });

  test('logging methods accept strings or an array', function() {
    var expected = ['hello', 'world'];
    Polymer.Base._log('hello', 'world');
    assert.deepEqual(logStub.args[0], expected, 'strings');
    Polymer.Base._log(['hello', 'world']);
    assert.deepEqual(logStub.args[1], expected, 'array');
  });

  test('logf will print the element name and function', function() {
    Child.created = function() {
      this._log(this._logf('ready', 'ready now!'));
    }
    instance.createdCallback();
    assert.equal(logStub.callCount, 1);
    var expected = Polymer.Base._logPrefix.concat([
      'x-child',
      'ready',
      'ready now!'
    ]);
    assert.deepEqual(logStub.args[0], expected);
  });
});
});
</script>
</body>
</html>
